<template>
    <div class="hello">
        <h3>泛型作用: 保证输入数组类型 与输出的东西类型 相同</h3>
        <h3>ts泛型函数，泛型接口，泛型类</h3>

    </div>
</template>

<script  lang="ts" >
    import { defineComponent } from 'vue'

    export default defineComponent({
            name: 'HelloWorld',
            props: {
                msg: String
            },
            setup(props,context){ // setup 不允许前面加async
                let str:string = "string"
                // 泛型函数
                function firstElement2<T>(arr: T[]): T | undefined {
                    return arr[0]
                }
                // 调用时类型一般不写
                firstElement2<string>(['a', 'b', 'c']) // string
                firstElement2<number>([1, 2, 3]) // number
                firstElement2([])// undefined

                // 指定输入类型与输出类型 (类型可以不一致)
                function mapfuc<I, O>(arr: I[], func: (arg: I) => O): O[] {  // Input 输入类型   Output输出，类型
                    return arr.map(func)
                }
                const parsed = mapfuc(['1', '2','30'], (n) => {console.log(parseInt(n)); return parseInt(n)})
                console.log(parsed)

                // 泛型约束
                function longest<T extends Array<any> | string>(a: T, b: T) { // 传进来的 a b 必须要有length 属性
                    if (a.length >= b.length) {
                        return a
                    } else {
                        return b
                    }
                }
                const longerArray = longest([1, 2], [2, 3, 4])
                // const longerArray2 = longest([1, 2], "123") // 这种情况 就自己把string 转成array 再入参
                console.log(longerArray.length)
                // const longerString = longest('felix', 'lu')
                // const notOk = longest(10, 100)  报错

                //断言在泛型的应用 (通过控制语句 输出不同的 类型)
                function minimumLength<T extends Array<any>>(obj: T, minimum: number): T {
                    if (obj.length >= minimum) {
                        return obj
                    } else {
                        return { length: minimum } as T // 断言成任意类型
                    }
                }
                const arr = minimumLength([1, 2, 3], 6)
                console.log(arr)

                function combine<T>(arr1: T[], arr2: T[]): T[] {
                    let arr:T[] = [...arr1,...arr2]
                    console.log(arr);
                    return arr
                }
                // 为什么需要指定数组类型？ 因为会根据第一个string数组 推断第二个也是数组类型。因此发生错误
                const arr0 = combine<string | number>(["string"], [1, 2, 3]) // 一般不会这样输入两个不同类型的泛型...

                /*传字符串或者数组*/
                function loggingIdentity<Type extends {length:number}>(arg: Array<Type> | Type): Type[] | Type {
                    console.log(arg.length)
                    return arg
                }
                loggingIdentity(["string","string"])
                loggingIdentity("sss")
                return {
                    str
                }
            }
        }
    )
</script>

<style scoped>

</style>
